#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sched.h>
#include <stdio.h>
#include <stdlib.h>

void void_thread() { }

int main(int argc, char *argv[]) {

  int good_open = 0;
  int wrong_open = 0;
  int good_close = 0;
  int wrong_close = 0;
  int good_write = 0;
  int wrong_write = 0;
  int good_lseek = 0;
  int wrong_lseek = 0;
  int good_clone = 0;
  int wrong_clone = 0;
  int pid = 0;
  int channel0 = 0;
  int channel1 = 0;
  char buffer[] = " ";
  int result = 0;
  void **stack;

  pid = getpid();
  
  printf("Fer la instalacio del modul passant-li com a parametre el pid d'aquest proces ( %d ) i premer una tecla per continuar.\n", pid);

  //Ens quedem bloquejats fins que no es prem una tecla
  fflush(stdout);
  read(0, buffer, 1);

  //A partir d'aquest punt hem de contar també tots els printf ja que hem començat a monitoritzar aquest procés, assumirem que els printf s'executen tots correctament

  printf("Inici del joc de proves~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
  good_write++;
  
  printf("Executant i provant OPEN...\n");
  good_write++;
  
  //Obrim un fitxer que no existeix
  channel0 = open("proso", O_RDWR);
  if (channel0 == -1) {
    wrong_open++;
  } else {
    good_open++;
  }
  
  //Obrim un fitxer amb flags O_CREAT (ja que no existeix)
  channel0 = open("proso", O_RDWR | O_CREAT);
  if (channel0 == -1) {
    wrong_open++;
  } else {
    good_open++;
  }
  
  //Obrim el mateix fitxer en un altre canal
  channel1 = open("proso", O_RDWR);
  if (channel1 == -1) {
    wrong_open++;
  } else {
    good_open++;
  }
  
  printf("Executant i provant WRITE...\n");
  good_write++;
  
  result = write(channel0,"segon projecte proso\n", 21);
  if (result >= 0) {
    good_write++;
  } else {
    wrong_write++;
  }

  //Produïm un error, intentem escriure en un canal negatiu
  
  result = write(-1,"segon projecte proso\n", 21);
  if (result >= 0) {
    good_write++;
  } else {
    wrong_write++;
  }
  
  printf("Executant i provant LSEEK...\n");
  good_write++;

  result = lseek(channel0, 0, SEEK_END);
  if (result >= 0) {
    good_lseek++;
  } else {
    wrong_lseek++;
  }

  //Produïm un error, fem lseek en un canal negatiu
  
  result = lseek(-1, 0, SEEK_END);
  if (result >= 0) {
    good_lseek++;
  } else {
    wrong_lseek++;
  }

  printf("Executant i provant CLOSE...\n");
  good_write++;
  
  result = close(-1);
  if (result >= 0) {
    good_close++;
  } else {
    wrong_close++;
  }

  result = close(channel0);
  if (result >= 0) {
    good_close++;
  } else {
    wrong_close++;
  }
  
  result = close(channel1);
  if (result >= 0) {
    good_close++;
  } else {
    wrong_close++;
  }  

  printf("Executant i provant CLONE...\n");
  good_write++;
    
  result = clone((void *) void_thread, stack, CLONE_VM, 0);
  if (result >= 0) {
    good_clone++;
  } else {
    wrong_clone++;
  }

  printf("Fi del joc de proves~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n");
  good_write++;

  unlink("proso"); //Evita que el primer joc de proves sigui diferent als següents degut a que en el segon ja existiria el fitxer "proso"
  
  // Afegim les 6 que imprimirem posteriorment degut a que sinó figurarien en la sortida del modul però no en la del joc de proves
  good_write +=6;
	printf("OPEN: entrades totals %d, sortides correctes %d, sortides incorrectes %d\n", good_open + wrong_open, good_open, wrong_open);
	printf("WRITE: entrades totals %d, sortides correctes %d, sortides incorrectes %d\n", good_write + wrong_write, good_write, wrong_write);
	printf("LSEEK: entrades totals %d, sortides correctes %d, sortides incorrectes %d\n", good_lseek + wrong_lseek, good_lseek, wrong_lseek);
	printf("CLOSE: entrades totals %d, sortides correctes %d, sortides incorrectes %d\n", good_close + wrong_close, good_close, wrong_close);
	printf("CLONE: entrades totals %d, sortides correctes %d, sortides incorrectes %d\n", good_clone + wrong_clone, good_clone, wrong_clone);
	printf("Desinstalar el modul i comparar.\n");
	while(1); 
}
